/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.compomics.fspike.contentprovider.uniprotontology;

import com.compomics.fspike.gui.taxonomytree.rendering.DefaultTaxonomyTreeNode;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Kenneth
 */
public class UniprotTaxonomyLookupService {

    private static boolean useableOnly;

    public static void main(String[] args) {
        try {
            printNode(querySingleNode("9606"));
            System.out.println("---------------");
            for (DefaultTaxonomyTreeNode node : queryPossibleNode("Homo Sapiens", 10, true)) {
                printNode(node);
            }
            System.out.println("---------------");
            System.out.println(getTaxonomyName("9605"));
            System.out.println("---------------");
            printNode(querySingleNode("131567"));
        } catch (URISyntaxException | IOException ex) {
            Logger.getLogger(UniprotTaxonomyLookupService.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void printNode(DefaultTaxonomyTreeNode querySingleNode) {
        System.out.println(querySingleNode);
        System.out.println("Parent is " + querySingleNode.getParentURL());
        System.out.println("Children are " + querySingleNode.getChildrenNameMap());
    }

    public static String getTaxonomyName(String taxonomyID) throws MalformedURLException, IOException {
        String nodeName = "";
        InputStream resource = new URL("http://www.uniprot.org/taxonomy/" + taxonomyID + "&format=rdf").openStream();
        //TODO change this to Jenna code?
        BufferedReader in = new BufferedReader(new InputStreamReader(resource));
        String inputLine;

        while ((inputLine = in.readLine()) != null) {
            if (inputLine.contains("scientificName")) {
                nodeName = getValueFromInputTag(inputLine);
            }
        }
        in.close();
        return nodeName;
    }

    public static String getTaxonomyID(String taxonomyName) throws MalformedURLException, IOException {
        String nodeName = "";
        InputStream resource = new URL("http://www.uniprot.org/taxonomy/?query=\"" + taxonomyName.replace(" ", "%20") + "\"&format=rdf").openStream();
        //TODO change this to Jenna code?
        BufferedReader in = new BufferedReader(new InputStreamReader(resource));
        String inputLine;
        boolean foundTax = false;
        while ((inputLine = in.readLine()) != null && !foundTax) {
            if (inputLine.contains("<rdf:Description rdf:about=")) {
                nodeName = getURLfromInput(inputLine);
                foundTax = true;
            }
        }
        in.close();
        return nodeName.substring(nodeName.lastIndexOf("/") + 1);
    }

    public static List<DefaultTaxonomyTreeNode> queryPossibleNode(String taxonomyTerms, int hitlimit, boolean usableOnly) throws MalformedURLException, IOException {
        List<DefaultTaxonomyTreeNode> possibleNodes = new LinkedList<>();
        taxonomyTerms = taxonomyTerms.replace(" ", "%20");
        String url;
        if (!useableOnly) {
            url = "http://www.uniprot.org/taxonomy/?query=\"" + taxonomyTerms + "\"&sort=score&limit=" + hitlimit + "&format=rdf";
        } else {
            url = "http://www.uniprot.org/taxonomy/?query=\"" + taxonomyTerms + "\"" + "+AND+%28complete%3Ayes+OR+reference%3Ayes%29&sort=score&limit=" + hitlimit + "&format=rdf";
        }
        BufferedReader in = new BufferedReader(new InputStreamReader(new URL(url).openStream()));
        String inputLine;
        LinkedHashMap<String, String> childrenURL = new LinkedHashMap<>();
        String nodeName = null;
        String parentURL = null;
        DefaultTaxonomyTreeNode queriedNode = null;
        while ((inputLine = in.readLine()) != null) {
            if (inputLine.contains("scientificName")) {
                if (queriedNode != null) {
                    queriedNode.setUrl("http://purl.uniprot.org/taxonomy/" + getTaxonomyID(nodeName) + "&format=rdf");
                    queriedNode.setChildrenNameMap(childrenURL);
                    childrenURL.clear();
                    possibleNodes.add(queriedNode);
                }
                nodeName = getValueFromInputTag(inputLine);
                if (nodeName.equalsIgnoreCase("homo sapiens")) {
                    System.out.println("yes");
                }
                queriedNode = new DefaultTaxonomyTreeNode(nodeName);
            }
            if (inputLine.contains("subClassOf")) {
                parentURL = getURLfromInput(inputLine);
                queriedNode.setParentURL(parentURL);
            }
            if (inputLine.contains("narrowerTransitive")) {
                String urLfromInput = getURLfromInput(inputLine);
                String childName = getTaxonomyName(urLfromInput.substring(urLfromInput.lastIndexOf("/") + 1));
                childrenURL.put(childName, urLfromInput);
            }
        }
        in.close();
        return possibleNodes;
    }

//------------------------------------------------------------------------------------------------------------------------  
    public static DefaultTaxonomyTreeNode querySingleNode(String taxonomyID) throws URISyntaxException, MalformedURLException, IOException {
        URL resource = new URL("http://www.uniprot.org/taxonomy/" + taxonomyID + "&sort=score&format=rdf");
        return parseURLInNode(resource);
    }

    private static DefaultTaxonomyTreeNode parseURLInNode(URL url) throws IOException {
        //TODO change this to Jenna code?
        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
        String inputLine;
        LinkedHashMap<String, String> childrenURL = new LinkedHashMap<>();
        String nodeName = null;
        String parentURL = null;
        String nodeURL = null;
        String parentName = null;
        while ((inputLine = in.readLine()) != null) {
            if (inputLine.contains("scientificName")) {
                nodeName = getValueFromInputTag(inputLine);
            }
            if (inputLine.contains("about")) {
                nodeURL = getURLfromInput(inputLine);
            }
            if (inputLine.contains("subClassOf")) {
                parentURL = getURLfromInput(inputLine);
                parentName = getTaxonomyName(parentURL.substring(parentURL.lastIndexOf("/") + 1));
            }
            if (inputLine.contains("narrowerTransitive")) {
                String urLfromInput = getURLfromInput(inputLine);
                String childName = getTaxonomyName(urLfromInput.substring(urLfromInput.lastIndexOf("/") + 1));
                childrenURL.put(childName, urLfromInput);
            }
        }
        in.close();
        DefaultTaxonomyTreeNode queriedNode = new DefaultTaxonomyTreeNode(nodeName);
        queriedNode.setParentURL(parentURL);
        queriedNode.setParentName(parentName);
        queriedNode.setUrl(nodeURL);
        queriedNode.setChildrenNameMap(childrenURL);
        return queriedNode;
    }

    //------------------------------------------------------------------------------------------------------------------------  
    public static void updateNode(DefaultTaxonomyTreeNode node) throws URISyntaxException, MalformedURLException, IOException {
        String nodeURL = node.getUrl();
        DefaultTaxonomyTreeNode tempNode;
        if (nodeURL == null || nodeURL.isEmpty()) {
            tempNode = parseURLInNode(new URL(node.getUrl()));
        } else {
            String nodeID = node.getUrl();
            nodeID = nodeID.substring(nodeID.lastIndexOf("/") + 1);
            tempNode = querySingleNode(nodeID);
        }
        node.setChildrenNameMap(tempNode.getChildrenNameMap());
        node.setParentName(tempNode.getParentName());
        node.setParentURL(tempNode.getParentURL());
    }

    private static String getURLfromInput(String inputLine) {
        int indexOf = inputLine.indexOf('"') + 1;
        int indexOf1 = inputLine.lastIndexOf('"');
        return inputLine.substring(indexOf, indexOf1);
    }

    private static String getValueFromInputTag(String inputLine) {
        int indexOf = inputLine.indexOf(">") + 1;
        int indexOf1 = inputLine.lastIndexOf("<");
        return inputLine.substring(indexOf, indexOf1);
    }

}
